#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "resourcemanager.h"
#include "sound.h"
#include "mesh.h"
#include "rawdataresource.h"
#include "game.h"
#include "texture.h"
#include "fxtexture.h"


/**
 * Konstruktor domyslny
 */
ResourceManager::ResourceManager()
{
	// ustaw katalog roboczy na katalog data
	SetCurrentDirectory("..\\..\\data\\");
}

/**
 * Destruktor
 */
ResourceManager::~ResourceManager()
{
	// zwolnij zasoby (zasoby zwalniaja sie same z listy w destruktorach!)
	resources.clear();
}


/**
 * Dodaje (laduje) zasob z pliku.
 *
 * @param fileName Nazwa pliku
 * @param type Typ zasobu
 * @return Zaladowany zasob lub NULL jesli wystapil blad.
 */
Resource* ResourceManager::addResource(const std::string &fileName, Resource::Type type)
{
	Resource* res = NULL;
	switch(type)
	{
	case Resource::MeshResource:
		res = new Mesh();
		break;
	case Resource::TextureResource:
		res = new Texture();
		break;
	case Resource::FxTextureResource:
		res = new FxTexture();
		break;
	case Resource::ImageResource:
		res = new Image();
		break;
	case Resource::SoundResource:
		res = new Sound();
		break;
	case Resource::LevelResource:
		res = new Level();
		break;
	case Resource::SavedGameResource:
		// res = new SavedGame();
		break;
	case Resource::RawDataResource:
		res = new RawDataResource();
		break;
	};
	if(!res)
		return NULL;

	// otworz plik
	res->addRef();
	res->name = fileName;
	if(!res->openFile(fileName))
	{
		res->release();
		return NULL;
	}

	// zaladuj zasob
	if(!res->load())
	{
		res->release();
		return NULL;
	}

	// dodaj do listy zasobow
	resources.push_back(res);

	return res;
}


/**
 * Dodaje wiele zasobow.
 *
 * @param fileNameMask Maska nazwy pliku (np "*.bmp")
 * @param type Typ zasobow
 * @return True jesli pomyslnie zaladowano wszystkie pasujace pliki, false jesli nie.
 */
bool ResourceManager::addResources(const std::string &fileNameMask, Resource::Type type, bool ignoreFails)
{
	WIN32_FIND_DATA findData;
	HANDLE hFind;

	// rozpocznij wyszukiwanie
	hFind = FindFirstFile(fileNameMask.c_str(), &findData);
	if(INVALID_HANDLE_VALUE == hFind)
		return false;
	
	// zaladuj zasob i wyszukaj dalej plikow
	do
	{
		if((NULL == addResource(std::string(findData.cFileName), type)) && !ignoreFails)
		{
			FindClose(hFind);
			return false;
		}
	} while(FindNextFile(hFind, &findData));

	// wszystkie zasoby zostaly pomyslnie zaladowane
	FindClose(hFind);
	return true;
}


/**
 * Zwraca zasob po jego nazwie (nazwie pliku).
 */
Resource* ResourceManager::getResourceByName(const std::string &resourceName) const
{
	std::list<Resource*>::const_iterator ci;
	for(ci = resources.begin(); ci != resources.end(); ci++)
	{
		if((*ci)->getName() == resourceName)
			return (*ci);
	}
	return NULL;
}

/**
 * Tworzy zasob zapisanej gry.
 */
Resource* ResourceManager::createSavedGameResource(const SavedGameState &state,
	const std::string &fileName)
{
	HANDLE hFile;

	// otworz plik
	hFile = CreateFile(fileName.c_str(), GENERIC_WRITE,
		0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(INVALID_HANDLE_VALUE == hFile)
		return NULL;
	
	// zapisz dane
	DWORD nWritten;
	WriteFile(hFile, &state, sizeof(SavedGameState), &nWritten, NULL);

	// zamknij plik
	CloseHandle(hFile);

	// dodaj i zwroc zasob
	return addResource(fileName, Resource::SavedGameResource);
}
